package com.soft.mainsite.common.exception;

import com.soft.mainsite.common.utils.ControllerUtil;
import com.soft.mainsite.common.utils.JsonUtil;
import com.soft.mainsite.module.staticstrategy.exception.HtmlStaticException;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.beetl.core.exception.BeetlException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * Description:自定义统一错误控制器
 *
 * @author Jin
 * @create 2017-04-09
 */
@Slf4j
@ControllerAdvice
public class DefaultExceptionHandler {


    /**
     * 接口异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler({ApiException.class})
    @ResponseBody
    public String apiException(Exception e) {
        return JsonUtil.toErrorResultJson(e.getMessage());
    }


    /**
     * cms异常
     *
     * @param e
     * @param request
     * @param response
     * @return
     */
    @ExceptionHandler({Exception.class})
    public ModelAndView cmsException(Exception e, HttpServletRequest request, HttpServletResponse response) {
        log.error("CmsException: e.toString == {}， e.getMessage == {}", e.toString(), e.getMessage());
        if (ControllerUtil.isAjaxRequest(request)) {
            ControllerUtil.renderErrorJson("系统错误，请通知技术人员", response);
            return null;
        } else {
            return this.renderErrorView(500, "HTTP-Internal Server Error", "系统错误，请通知技术人员");
        }
    }

    @ExceptionHandler(value = NoHandlerFoundException.class)
    public String handleException(HttpServletRequest request, NoHandlerFoundException exception) {
        log.error(exception.getMessage(), exception);
        request.setAttribute("exception", exception);
        return "404";
    }


    /**
     * 系统异常
     *
     * @param e
     * @param request
     * @param response
     * @return
     */
    @ExceptionHandler({SystemException.class, CmsException.class, BeetlException.class})
    public ModelAndView systemException(Exception e, HttpServletRequest request, HttpServletResponse response) {
        log.error("SystemException:{}", e.getMessage());
        if (ControllerUtil.isAjaxRequest(request)) {
            ControllerUtil.renderErrorJson(e.getMessage(), response);
            return null;
        } else {
            return this.renderErrorView(500, "HTTP-Internal Server Error", e.getMessage());
        }
    }


    /**
     * 访问异常
     *
     * @param e
     * @param request
     * @param response
     * @return
     */
    @ExceptionHandler({UnauthenticatedException.class, AuthenticationException.class})
    public ModelAndView authenticationException(Exception e, HttpServletRequest request, HttpServletResponse response) {
        log.error("authenticationException:{}", e.getMessage());
        if (ControllerUtil.isAjaxRequest(request)) {
            // 输出JSON
            ControllerUtil.renderTimeoutJson("对不起，请登录后再访问！", response);
            return null;
        } else {
            return this.renderErrorView(401, "Authentication Failed", e.getMessage());
        }
    }

    /**
     * 权限异常
     *
     * @param e
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler({UnauthorizedException.class, AuthorizationException.class})
    public ModelAndView authorizationException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException {
        log.error("authorizationException:{}", e.getMessage());
        if (ControllerUtil.isAjaxRequest(request)) {
            // 输出JSON
            ControllerUtil.renderErrorJson("对不起，您没有此权限", response);
            return null;
        } else {
            return this.renderErrorView(401, "Unauthorized", e.getMessage());
        }
    }

    /**
     * 统一页面静态化异常
     *
     * @param e
     * @param request
     * @param response
     * @return
     */
    @ExceptionHandler({HtmlStaticException.class})
    public ModelAndView htmlStaticException(Exception e, HttpServletRequest request, HttpServletResponse response) {
        log.error("htmlStaticException:{}", e.getMessage());
        if (ControllerUtil.isAjaxRequest(request)) {
            // 输出JSON
            ControllerUtil.renderErrorJson(e.getMessage(), response);
            return null;
        } else {
            return this.renderErrorView(500, "HTTP-Internal Server Error", e.getMessage());
        }

    }


    private ModelAndView renderErrorView(Integer errorCode, String error, String message) {
        ModelAndView view = new ModelAndView("error");
        view.addObject("status", errorCode);
        view.addObject("error", error);
        view.addObject("message", message);
        view.addObject("timestamp", new Date());
        return view;
    }

}
